﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;

namespace huqiang.Core.HGUI
{
    [Serializable]
    public class HPolygon:HGraphics
    {
        static bool Snip(int u, int v, int w, int n, int[] tris, List<Vector2> points)
        {
            Vector2 a = points[tris[u]];
            Vector2 b = points[tris[v]];
            Vector2 c = points[tris[w]];
            if (Mathf.Epsilon > ((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)))//内角小于180
                return false;
            for (int i = 0; i < n; i++)
            {
                if (i == u || i == v || i == w)
                    continue;
                Vector2 p = points[tris[i]];
                if (huqiang.Physics2D.DotToTriangle(ref a, ref b, ref c, ref p))
                    return false;
            }
            return true;
        }
        static float Area(List<Vector2> points)
        {
            int c = points.Count;
            float a = 0;
            for (int p = c - 1, q = 0; q < c; p = q++)
            {
                Vector2 pv = points[p];
                Vector2 qv = points[q];
                a += pv.x * qv.y - qv.x * pv.y;
            }
            return a * 0.5f;
        }
        public static int[] Triangulate(List<Vector2> points)
        {
            List<int> indices = new List<int>();
            int n = points.Count;
            if (n < 3)
                return indices.ToArray();
            int[] V = new int[n];
            if (Area(points) > 0) // 将所有顶点按照顺时针方向排列
            {
                for (int v = 0; v < n; v++)
                    V[v] = v;
            }
            else
            {
                for (int v = 0; v < n; v++)
                    V[v] = (n - 1) - v;
            }
            int nv = n;
            int count = 2 * nv;
            for (int v = nv - 1; nv > 2;)// 开始迭代
            {
                if ((count--) <= 0)
                    return indices.ToArray();
                int u = v;
                if (nv <= u)
                    u = 0;
                v = u + 1;
                if (nv <= v)
                    v = 0;
                int w = v + 1;
                if (nv <= w)
                    w = 0;
                if (Snip(u, v, w, nv, V, points))
                {
                    int a, b, c, s, t;
                    a = V[u];
                    b = V[v];
                    c = V[w];
                    indices.Add(a);
                    indices.Add(b);
                    indices.Add(c);
                    for (s = v, t = v + 1; t < nv; s++, t++)
                        V[s] = V[t];
                    nv--;
                    count = 2 * nv;
                }
            }
            indices.Reverse();
            return indices.ToArray();
        }
        [SerializeField]
        List<Vector2> m_points = new List<Vector2>();

        public override void UpdateMesh()
        {
            if (m_dirty)
            {
                mesh.tris = Triangulate(m_points);
                int c = m_points.Count;
                if (c > mesh.vertInfo.Size | c + 32 < mesh.vertInfo.Size)
                {
                    mesh.vertInfo.Size = c;
                }
                for (int i = 0; i < c; i++)
                {
                    unsafe
                    {
                        var p = m_points[i];
                        mesh.vertInfo.Addr[i].position = p;
                        mesh.vertInfo.Addr[i].uv.x = p.x / m_sizeDelta.x + 0.5f;
                        mesh.vertInfo.Addr[i].uv.y = p.y / m_sizeDelta.y + 0.5f;
                        mesh.vertInfo.Addr[i].color = m_color;
                    } 
                }
                mesh.vertInfo.DataCount = c;
            }
        }
    }
}
